package com.iknight.theory.service.impl;

import com.iknight.mgr.core.utils.IkgNumberUtils;
import com.iknight.mgr.core.utils.IkgStringUtils;
import com.iknight.mgr.core.utils.IkgWebUtils;
import com.iknight.theory.api.TheoryCalService;
import com.iknight.theory.mapper.*;
import com.iknight.theory.model.*;
import com.iknight.theory.tree.EquipTreeNode;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class TheoryCalServiceImpl implements TheoryCalService {
    private final Logger logger = LogManager.getLogger(TheoryCalServiceImpl.class);

    @Autowired
    private TPCurrentMapper<TPCurrentModel, String> tpCurrentMapper;
    @Autowired
    private TeTranMapper<TETranModel, String> teTranMapper;
    @Autowired
    private TeLineMapper<TELineModel, String> teLineMapper;
    @Autowired
    private TeRecordMapper<TPRecordModel, String> teRecordMapper;
    @Autowired
    private TeLineSegMapper<TELineSegModel, String> teLineSegMapper;
    @Autowired
    private TeLineConsMapper<TELineConsModel, String> teLineConsMapper;
    @Autowired
    private TeContainerMapper<TEContainerModel, String> teContainerMapper;
    /**
     * 计算日志
     */
    private StringBuffer calLog;

    @Override
    public Object validateArchive(String tranId, String code) {
        calLog = new StringBuffer(100);
        String msg = null;
        boolean checkSuccess = true;
        Map result = new HashMap();
        TETranModel tranModel = teTranMapper.selectOne(tranId);
        if (null == tranModel) {
            msg = "未通过配电变压器检测，计算终止";
            recordLoggs(code, msg);
            result.put("success", false);
            return result;
        } else {
            msg = "通过配电变压器档案检测";
            result.put("tran", tranModel);
            recordLoggs(code, msg);
        }

        Map lineCheckResult = (Map) this.checkLine(tranId, code, msg);
        checkSuccess = (boolean) lineCheckResult.get("success");
        if (!checkSuccess) {
            result.put("success", checkSuccess);
            return result;
        }
        /************************完成低压线路校验***********************************/
        String lineId = IkgStringUtils.ObjectToString(lineCheckResult.get("lineId"));
        Map lineSegCheckResult = (Map) checkLineSeg(lineId, code, msg);

        checkSuccess = (boolean) lineSegCheckResult.get("success");
        if (!checkSuccess) {
            result.put("success", checkSuccess);
            return result;
        }
        List<Map> segls = (List<Map>) lineSegCheckResult.get("result");
        /************************完成低压线路分段校验***********************************/

        Map consLineCheckResult = (Map) checkConsLine(lineId, code, msg);
        checkSuccess = (boolean) consLineCheckResult.get("success");
        if (!checkSuccess) {
            result.put("success", checkSuccess);
            return result;
        }
        result.put("segls", segls);

        List<Map> consLinels = (List<Map>) consLineCheckResult.get("result");

        /************************完成低压下户线校验***********************************/
        //container check 表箱电量
        /**
         * 未进行表箱挂接杆塔检测
         */

        /************************完成表箱档案数据校验******************************/
        Map consChekcResult = (Map) checkCons(lineId, code, msg);
        checkSuccess = (boolean) consChekcResult.get("success");
        if (!checkSuccess) {
            result.put("success", false);
            return result;
        }
        result.put("consLinels", consLinels);

        List<Map> consPowerls = (List<Map>) consChekcResult.get("result");
        result.put("consPowerls", consPowerls);

        /************************完成低压用户校验***********************************/
        //查询配变电量
        Map queryParam = new HashMap();
        queryParam.put("equip_id", tranId);
        queryParam.put("data_type", "01");
        List<Map> ygls = teRecordMapper.getPowerByParam(queryParam);
        if (ygls.size() != 1) {
            msg = "未通过配变有功电量数据完整性校验。";
        } else {
            msg = "通过配变有功电量数据完整性校验。";
        }
        recordLoggs(code, msg);
        queryParam.put("data_type", "02");
        List<Map> wgls = teRecordMapper.getPowerByParam(queryParam);
        if (wgls.size() != 1) {
            msg = "未通过配变无功电量数据完整性校验。";
        } else {
            msg = "通过配变无功电量数据完整性校验。";
        }
        recordLoggs(code, msg);

        //功率因数 power_factor
        queryParam.put("data_type", "03");
        List<Map> glys = teRecordMapper.getPowerByParam(queryParam);
        double powerFactor = 0;
        if (glys.size() == 0) {
            msg = "未检测到功率因数数据，系统默认为1。";
            powerFactor = 1;
        } else if (glys.size() == 1) {
            powerFactor = IkgNumberUtils.objectToDouble(glys.get(0).get("data_value"));
            msg = "通过功率因数检测，系统值为" + powerFactor;
        } else if (glys.size() > 1) {
            msg = "检测到多个功率因数，系统将默认取最大值";
            powerFactor = 1;
        }

        result.put("powerFactor", powerFactor);
        recordLoggs(code, msg);
        /************************完成配电变压器电量校验***********************************/

        msg = "开始进行数据有效性校验。";
        recordLoggs(code, msg);

        //比对配变正向有功电量与低压用户合计电量
        DecimalFormat df = new DecimalFormat("#.0000");

        double tranPower = Double.valueOf(ygls.get(0).get("data_value").toString());
        result.put("tranPower", tranPower);

        double consPower = 0;
        for (Map power : consPowerls) {
            consPower += Double.valueOf(power.get("power_value").toString());
        }
        if (consPower >= tranPower) {
//            checkSuccess = false;
            msg = "未通过电量偏差校验!配变有功电量[" + df.format(tranPower) + "kWh],低压用户电量合计[" + df.format(consPower) + "kWh]";
            recordLoggs(code, msg);
        } else {
            msg = "通过电量偏差校验！配变有功电量[" + df.format(tranPower) + "kWh]低压用户电量合计[" + df.format(consPower) + "kWh]";
            recordLoggs(code, msg);
        }
        result.put("consPower", consPower);
        result.put("success", checkSuccess);
        return result;
    }

    @Override
    public Object checkLineSeg(String lineId, String code, String msg) {
        Map result = new HashMap();

        List<Map> segls = teLineSegMapper.getSegsByLineId(lineId);
        boolean checkSuccess = true;

        if (null == segls || (null != segls && segls.size() == 0)) {
            msg = "未校验到低压线路分段，计算终止。";
            recordLoggs(code, msg);
            checkSuccess = false;
        } else {
            int segSucNum = segls.size();
            int total = segSucNum;
            boolean isStartedByTran = false;//用于判断是否自配变起始
            int isMultiStartedByTran = 0;

            List<String> segArray = new ArrayList<>();
            for (Map seg : segls) {
                segArray.add(IkgStringUtils.ObjectToString(seg.get("end_pos")));
            }

            for (Map seg : segls) {//进行属性校验，包括长度、型号缺失
                boolean checkSegSuc = true;
                String segLength = IkgStringUtils.ObjectToString(seg.get("seg_length"));//获得长度
                String startType = IkgStringUtils.ObjectToString(seg.get("start_type"));//获得起点类型
                if (startType.equals("01")) {
                    isStartedByTran = true;
                    isMultiStartedByTran++;
                }

                if (segLength.length() == 0 || Double.valueOf(segLength) == 0) {
                    checkSegSuc = false;
                    msg = "校验到低压线路分段,编号[" + seg.get("seg_no") + "]长度为0。";
                    recordLoggs(code, msg);
                }

                String modelNo = IkgStringUtils.ObjectToString(seg.get("model_no"));
                if (modelNo.length() == 0) {
                    checkSegSuc = false;
                    msg = "校验到低压线路分段,编号[" + seg.get("seg_no") + "],未维护线段型号。";
                    recordLoggs(code, msg);
                }
                String resistance = IkgStringUtils.ObjectToString(seg.get("resistance_value"));
                resistance = resistance.length() == 0 ? "0" : resistance;
                if (Double.valueOf(resistance) == 0) {
                    checkSegSuc = false;
                    msg = "校验到低压线路分段,编号[" + seg.get("seg_no") + "],型号未维护电阻。";
                    recordLoggs(code, msg);
                }
                //判断是否有起始、终止位置
                String startPos = IkgStringUtils.ObjectToString(seg.get("start_pos"));//获得起点位置
                if (!IkgStringUtils.isNotNull(startPos)) {
                    checkSegSuc = false;

                    msg = "校验到低压线路分段,编号[" + seg.get("seg_no") + "],缺失起始位置信息维护。";
                    recordLoggs(code, msg);
                }
                //判断起点位置是否有孤岛
                if (!startType.equals("01") && !IkgStringUtils.findKeyInArray(segArray, startPos)) {
                    checkSegSuc = false;

                    msg = "校验到低压线路分段,编号[" + seg.get("seg_no") + "]为孤岛分段。";
                    recordLoggs(code, msg);
                }

                String endPos = IkgStringUtils.ObjectToString(seg.get("end_pos"));//获得终点位置
                if (!IkgStringUtils.isNotNull(endPos)) {
                    checkSegSuc = false;
                    msg = "校验到低压线路分段,编号[" + seg.get("seg_no") + "],缺失终止位置信息维护。";
                    recordLoggs(code, msg);
                }

                if (!checkSegSuc) {
                    segSucNum--;
                    checkSuccess = false;
                }
            }

            if (!isStartedByTran) {
                msg = "未检测到分段线路自配电变压器接出，档案完整性校验失败。";
                recordLoggs(code, msg);
                checkSuccess = false;
            }
            if (isMultiStartedByTran > 1) {
                msg = "检测到有多条分段线路起始于配电变压器，档案完整性校验失败。";
                recordLoggs(code, msg);
                checkSuccess = false;
            }
            if (checkSuccess) {
                msg = "线路分段条数为：" + total + "条，通过线路分段完整性校验。";
                recordLoggs(code, msg);
            } else {
                msg = "未通过低压线路分段完整性校验，总条数[" + total + "],失败[" + (total - segSucNum) + "]，计算终止。";
                recordLoggs(code, msg);
            }
        }
        result.put("success", checkSuccess);
        result.put("result", segls);
        return result;
    }

    @Override
    public Object checkLine(String tranId, String code, String msg) {
        Map result = new HashMap();
        boolean checkSuccess = true;
        Object line = teLineMapper.getLineInfoByTranId(tranId);
        String lineId = null;

        if (line instanceof TELineModel) {
            lineId = ((TELineModel) line).getLine_id();
        } else if (line instanceof List) {
            if (((List) line).size() == 1) {
                lineId = ((TELineModel) ((List) line).get(0)).getLine_id();
            } else {
                checkSuccess = false;
            }
        } else {
            checkSuccess = false;
        }
        if (!checkSuccess) {
            msg = "未校验到低压线路，计算终止。";
            recordLoggs(code, msg);
        } else {
            msg = "通过低压线路校验。";
            recordLoggs(code, msg);
        }
        result.put("success", checkSuccess);
        result.put("lineId", lineId);
        return result;
    }

    @Override
    public Object checkConsLine(String lineId, String code, String msg) {
        Map result = new HashMap();
        boolean checkSuccess = true;
        List<Map> consLinels = teLineConsMapper.getLineConsByLineId(lineId);

        if (null == consLinels || (null != consLinels && consLinels instanceof List && consLinels.size() == 0)) {

            msg = "未校验到下户线信息，档案缺失，计算终止。";
            recordLoggs(code, msg);
            checkSuccess = false;
        } else {
            int consLineSize = consLinels.size();
            int total = consLineSize;

            for (Map consLine : consLinels) {

                boolean checkClSuc = true;

                String clLength = IkgStringUtils.ObjectToString(consLine.get("cl_length"));
                clLength = clLength.length() == 0 ? "0" : clLength;

                if (Double.valueOf(clLength) == 0) {
                    checkClSuc = false;
                    msg = "校验到低压下户线,编号[" + consLine.get("cl_no") + "]长度为0。";
                    recordLoggs(code, msg);
                }

                String clModel = IkgStringUtils.ObjectToString(consLine.get("cl_model"));
                if (clModel.length() == 0) {
                    checkClSuc = false;
                    msg = "校验到低压下户线,编号[" + consLine.get("cl_no") + "],未维护下户线型号。";
                    recordLoggs(code, msg);
                }

                String resistance = IkgStringUtils.ObjectToString(consLine.get("resistance_value"));
                resistance = resistance.length() == 0 ? "0" : resistance;
                if (Double.valueOf(resistance) == 0) {
                    checkClSuc = false;

                    msg = "校验到低压下户线,编号[" + consLine.get("cl_no") + "],型号未维护电阻。";
                    recordLoggs(code, msg);
                }

                String linkedPole = IkgStringUtils.ObjectToString(consLine.get("start_pos"));
                if (linkedPole.length() == 0) {
                    checkClSuc = false;
                    msg = "校验到低压下户线,编号[" + consLine.get("cl_no") + "],未维护挂接杆塔。";
                    recordLoggs(code, msg);
                }

                if (!checkClSuc) {
                    consLineSize--;
                    checkSuccess = false;
                }
            }

            if (checkSuccess) {
                msg = "低压下户线条数为：" + total + "条，通过下户线完整性校验。";
                recordLoggs(code, msg);
            } else {
                msg = "未通过低压下户线完整性校验，总条数[" + total + "],失败[" + (total - consLineSize) + "]，计算终止。";
                recordLoggs(code, msg);
            }
        }
        result.put("success", checkSuccess);
        result.put("result", consLinels);
        return result;
    }

    @Override
    public Object checkCons(String lineId, String code, String msg) {
        Map result = new HashMap();
        boolean checkSuccess = true;

        List<Map> consPowerls = teContainerMapper.getConsPowerByLine(lineId);
        if (null == consPowerls || (consPowerls != null && consPowerls instanceof List && consPowerls.size() == 0)) {
            msg = "未校验到用户及电量信息，计算终止。";
            recordLoggs(code, msg);
            checkSuccess = false;
        } else {
            int cpNum = consPowerls.size();
            int total = cpNum;
            for (Map consPower : consPowerls) {
                boolean checkCPSuc = true;
                String powerValue = IkgStringUtils.ObjectToString(consPower.get("power_value"));
                powerValue = powerValue.trim().length() == 0 ? "0" : powerValue;

                if (Double.valueOf(powerValue) == 0) {
                    checkCPSuc = false;
                    msg = "校验到表箱,编号[" + consPower.get("asset_no") + "],合计电量为0。";
                    recordLoggs(code, msg);
                }
                if (!checkCPSuc) {
                    cpNum--;
                    if (cpNum == 0) {
                        checkSuccess = false;
                    }
                }
            }

            if (checkSuccess) {
                msg = "低压用户电量条数为：" + total + "条，通过用户电量完整性校验。";
                recordLoggs(code, msg);
            } else {
                msg = "未通过低压用户电量完整性校验，总条数[" + total + "],失败[" + (total - cpNum) + "]，计算终止。";
                recordLoggs(code, msg);
            }
        }

        result.put("success", checkSuccess);
        result.put("result", consPowerls);

        return result;
    }

    @Override
    public Object calThreePhaseUnbalance(String tran_id) {
        Map result = new HashMap();
        Map map = new HashMap();
        map.put("tran_id", tran_id);
        List<Double> currentLs = new ArrayList<>();

        List<TPCurrentModel> tpCurrentModels = tpCurrentMapper.selectByCond(map);
        for (TPCurrentModel model : tpCurrentModels) {
            currentLs.add(model.getValue_0());
            currentLs.add(model.getValue_1());
            currentLs.add(model.getValue_2());
            currentLs.add(model.getValue_3());
            currentLs.add(model.getValue_4());
            currentLs.add(model.getValue_5());
            currentLs.add(model.getValue_6());
            currentLs.add(model.getValue_7());
            currentLs.add(model.getValue_8());
            currentLs.add(model.getValue_9());
            currentLs.add(model.getValue_10());
            currentLs.add(model.getValue_11());
            currentLs.add(model.getValue_12());
            currentLs.add(model.getValue_13());
            currentLs.add(model.getValue_14());
            currentLs.add(model.getValue_15());
            currentLs.add(model.getValue_16());
            currentLs.add(model.getValue_17());
            currentLs.add(model.getValue_18());
            currentLs.add(model.getValue_19());
            currentLs.add(model.getValue_20());
            currentLs.add(model.getValue_21());
            currentLs.add(model.getValue_22());
            currentLs.add(model.getValue_23());
        }
        if (currentLs.size() > 0) {
            Collections.sort(currentLs);
            BigDecimal bdMax = IkgNumberUtils.roundDouble(currentLs.get(currentLs.size() - 1), 2);
            double iAvg = 0;
            for (double value : currentLs) {
                iAvg += value;
            }
            BigDecimal bdTotal = IkgNumberUtils.roundDouble(iAvg, 4);
            BigDecimal bdAvg = bdTotal.divide(new BigDecimal(currentLs.size()), 2, BigDecimal.ROUND_HALF_UP);
            BigDecimal bdBaseValue = bdMax.subtract(bdAvg);
            bdBaseValue = bdBaseValue.divide(bdAvg, 4, BigDecimal.ROUND_HALF_UP);
            BigDecimal bdThree = new BigDecimal(3);
            BigDecimal bdEight = new BigDecimal(8);
            BigDecimal bdOne = new BigDecimal(1);
            BigDecimal bdTwo = new BigDecimal(2);
            //一相负荷重，两相负荷轻 公式=1+2a*a
            BigDecimal bdK1 = bdBaseValue.pow(2);
            bdK1 = bdK1.multiply(bdTwo);
            bdK1 = bdK1.add(bdOne);
            //一相负荷中，一相负荷轻，一相负荷平均 =1+8*a*a/3
            BigDecimal bdK2 = bdBaseValue.pow(2);
            bdK2 = bdK2.multiply(bdEight).divide(bdThree, 4, BigDecimal.ROUND_HALF_UP);
            bdK2 = bdThree.add(bdK2);
            //一相负荷轻，两相负荷重  =3+8*a*a
            BigDecimal bdK3 = bdBaseValue.pow(2).multiply(bdEight);
            bdK3 = bdThree.add(bdK3);

            result.put("max", bdMax.setScale(4, BigDecimal.ROUND_HALF_UP));
            result.put("avg", bdAvg.setScale(4, BigDecimal.ROUND_HALF_UP));
            result.put("k1", bdK1.setScale(4, BigDecimal.ROUND_HALF_UP));
            result.put("k2", bdK2.setScale(4, BigDecimal.ROUND_HALF_UP));
            result.put("k3", bdK3.setScale(4, BigDecimal.ROUND_HALF_UP));
        }

        return result;
    }

    @Override
    public BigDecimal calSinglePhaseCurrent(BigDecimal tranPower, BigDecimal tranPowerFacotr, BigDecimal avgVolt, BigDecimal calCycle) {
        BigDecimal bdPower = IkgNumberUtils.roundDouble(Math.sqrt(3), 4).multiply(avgVolt);
        bdPower = bdPower.multiply(calCycle);
        bdPower = bdPower.multiply(tranPowerFacotr);
        BigDecimal tranIav = tranPower.divide(bdPower, 4, BigDecimal.ROUND_HALF_UP);
        return tranIav;
    }

    @Override
    public Object calSegsPower(String recordId, List<?> segls, String code) {
        Map result = new HashMap();

        List<SegPowerInfo> lineSegPowerInfols = new ArrayList<>();
        List<EquipTreeNode> lineTreeNodes = new ArrayList<>();
        String msg;
        for (Object object : segls) {
            Map seg = (Map) object;
            EquipTreeNode node = new EquipTreeNode();
            node.setId(IkgStringUtils.ObjectToString(seg.get("end_pos")));
            node.setpId(IkgStringUtils.ObjectToString(seg.get("start_pos")));//上一节点
            node.setEquipId(IkgStringUtils.ObjectToString(seg.get("seg_id")));
            node.setEquipType(IkgStringUtils.ObjectToString(seg.get("start_type")));

            lineTreeNodes.add(node);

            SegPowerInfo info = new SegPowerInfo();

            info.setObj_id(IkgStringUtils.getUUID());
            info.setMain_record_id(recordId);
            info.setSeg_id(IkgStringUtils.ObjectToString(seg.get("seg_id")));
            BigDecimal bdSegLen = BigDecimal.valueOf(Double.valueOf(String.valueOf(seg.get("seg_length")))).setScale(4, BigDecimal.ROUND_HALF_UP);
            info.setSeg_length(bdSegLen.doubleValue());
            BigDecimal bdResistance = new BigDecimal(IkgStringUtils.ObjectToString(seg.get("resistance_value")));
            info.setUnit_resistance(bdResistance.setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue());
            BigDecimal bdUnitResistance = bdSegLen.divide(new BigDecimal(1000), 4, BigDecimal.ROUND_HALF_UP).multiply(bdResistance);
            bdUnitResistance = bdUnitResistance.setScale(4, BigDecimal.ROUND_HALF_UP);
            info.setUnit_resistance(bdUnitResistance.doubleValue());

            lineSegPowerInfols.add(info);

            msg = "分段[" + seg.get("seg_no") + "]," +
                    "长度[" + bdSegLen + "m]，" +
                    "电阻[" + bdUnitResistance + "Ω]。";
            recordLoggs(code, msg);
        }
        result.put("lineSegPower", lineSegPowerInfols);
        result.put("lineTreenodes", lineTreeNodes);
        return result;
    }

    @Override
    public Object analyzeLinePoles(List<Map> consLinels, List<Map> consPowerls) {
        List<Map> polePowers = new ArrayList<>();
        for (Map consLine : consLinels) {
            Map map = new HashMap();
            map.put("pole_id", consLine.get("start_pos"));
            map.put("container_id", consLine.get("container_id"));
            for (Map cp : consPowerls) {
                if (cp.get("container_id").equals(consLine.get("container_id"))) {
                    map.put("power_value", cp.get("power_value"));
                }
            }
            polePowers.add(map);
        }

        List<Map> fixedPolePowers = new ArrayList<>(new HashSet<>(polePowers));//去掉重复项

        return fixedPolePowers;
    }

    @Override
    public Object analyzeLineSegsPower(BigDecimal bdTranPower, BigDecimal bdConsPower, List<Map> segls, List<SegPowerInfo> lineSegPowerInfols) {
        //获得首端，并进行首端计算
        String frontSegId = null;
        for (Map<String, String> param : segls) {
            if (param.get("start_type").equals("01")) {
                frontSegId = param.get("seg_id");
            }
        }
        //P首端*P线路末端用户电量/P线路首端用户电量
        for (int i = 0; i < lineSegPowerInfols.size(); i++) {
            if (lineSegPowerInfols.get(i).getSeg_id().equals(frontSegId)) {//首端
                BigDecimal bdRestPower = IkgNumberUtils.roundDouble(lineSegPowerInfols.get(i).getRest_power(), 4);

                BigDecimal pInput = bdTranPower.multiply(bdRestPower).divide(bdConsPower, 4, BigDecimal.ROUND_HALF_UP);
                pInput = pInput.setScale(4, BigDecimal.ROUND_HALF_UP);

                BigDecimal actLoss = IkgNumberUtils.roundDouble(lineSegPowerInfols.get(i).getAct_loss(), 4);
                BigDecimal pOut = pInput.subtract(actLoss).setScale(4, BigDecimal.ROUND_HALF_UP);

                BigDecimal rate_seg_loss = actLoss.divide(pInput, 8, BigDecimal.ROUND_HALF_UP);
                rate_seg_loss = rate_seg_loss.multiply(new BigDecimal(100));
                rate_seg_loss = rate_seg_loss.setScale(4, BigDecimal.ROUND_HALF_UP);//保留4位

                lineSegPowerInfols.get(i).setSeg_input(pInput.doubleValue());//输送电量
                lineSegPowerInfols.get(i).setSeg_output(pOut.doubleValue());//售出电量
                lineSegPowerInfols.get(i).setSeg_loss_rate(rate_seg_loss.doubleValue());
                lineSegPowerInfols.get(i).setUnit_caled(true);//是否计算
            }
        }
        /*
            进行遍历,
            判断当前是否完成计算，如果没有，判断上一节点是否计算，如果有，则进行计算，如果没有，继续
         */

        boolean isCalWhole = false;
        List<Map> caledSegs = new ArrayList<>();

        for (Map map : segls) {
            caledSegs.add(map);
        }

        while (!isCalWhole) {
            for (int m = 0; m < caledSegs.size(); m++) {
                Map map = caledSegs.get(m);

                String segId = IkgStringUtils.ObjectToString(map.get("seg_id"));
                String startPos = IkgStringUtils.ObjectToString(map.get("start_pos"));

                for (int kk = 0; kk < lineSegPowerInfols.size(); kk++) {
                    SegPowerInfo info = lineSegPowerInfols.get(kk);
                    if (segId.equals(info.getSeg_id()) && !info.isUnit_caled()) {
                        //判断上一节点
                        for (Map tempMap : segls) {
                            String end_pos = IkgStringUtils.ObjectToString(tempMap.get("end_pos"));
                            String lastSegId = IkgStringUtils.ObjectToString(tempMap.get("seg_id"));

                            if (end_pos.equals(startPos)) {
                                for (int i = 0; i < lineSegPowerInfols.size(); i++) {
                                    SegPowerInfo spi = lineSegPowerInfols.get(i);
                                    if (spi.getSeg_id().equals(lastSegId) && spi.isUnit_caled()) {
                                        BigDecimal bdLastRestPower = IkgNumberUtils.roundDouble(spi.getRest_power(), 4);
                                        BigDecimal bdOutPower = IkgNumberUtils.roundDouble(spi.getSeg_output(), 4);
                                        BigDecimal bdRestPower = IkgNumberUtils.roundDouble(info.getRest_power(), 4);
                                        BigDecimal pInput = IkgNumberUtils.roundDouble(0, 4);
                                        BigDecimal pOut = IkgNumberUtils.roundDouble(0, 4);
                                        BigDecimal actLoss = IkgNumberUtils.roundDouble(info.getAct_loss(), 4);
                                        BigDecimal rate_seg_loss = IkgNumberUtils.roundDouble(0, 8);

                                        if (!bdLastRestPower.equals(BigDecimal.ZERO) && !bdLastRestPower.equals(IkgNumberUtils.roundDouble(0, 4))) {
                                            pInput = bdOutPower.multiply(bdRestPower);
                                            pInput = pInput.divide(bdLastRestPower, 4, BigDecimal.ROUND_HALF_UP);
                                            pOut = pInput.subtract(actLoss);
                                            if (!pInput.equals(BigDecimal.ZERO) && !pInput.equals(IkgNumberUtils.roundDouble(0, 4))) {
                                                rate_seg_loss = pOut.divide(pInput, 8, BigDecimal.ROUND_HALF_UP);
                                                rate_seg_loss = IkgNumberUtils.roundDouble(1, 8).subtract(rate_seg_loss);
                                                rate_seg_loss = rate_seg_loss.multiply(IkgNumberUtils.roundDouble(100, 4));
                                            }
                                        }

                                        lineSegPowerInfols.get(kk).setSeg_input(pInput.doubleValue());
                                        lineSegPowerInfols.get(kk).setSeg_output(pOut.doubleValue());
                                        lineSegPowerInfols.get(kk).setSeg_loss_rate(rate_seg_loss.doubleValue());
                                        lineSegPowerInfols.get(kk).setUnit_caled(true);

                                        caledSegs.remove(map);
                                    } else {
                                        continue;
                                    }
                                }
                            }
                        }
                    }
                }
            }

            int count = 0;
            for (SegPowerInfo spi : lineSegPowerInfols) {
                if (spi.isUnit_caled()) {
                    count++;
                }
            }
            if (count == lineSegPowerInfols.size()) {
                isCalWhole = true;
            }
        }
        return lineSegPowerInfols;
    }

    @Override
    public BigDecimal calLossRate(BigDecimal bdPowerLoss, BigDecimal bdPowerTotal) {
        BigDecimal bdHundrend = new BigDecimal(100);
        BigDecimal bdRate = bdPowerLoss.divide(bdPowerTotal, 4, BigDecimal.ROUND_HALF_UP);
        bdRate = bdRate.multiply(bdHundrend);
        return bdRate.setScale(4, BigDecimal.ROUND_HALF_UP);
    }

    @Override
    public BigDecimal calLoadCurseIndex(BigDecimal bdFrontAvgCurrent, BigDecimal bdLoadAvgCurrent, BigDecimal bdMax) {
        BigDecimal bdOne = new BigDecimal(1).setScale(4, BigDecimal.ROUND_HALF_UP);
        BigDecimal bdArgsA = bdOne.subtract(bdMax);
        bdArgsA = bdArgsA.divide(bdFrontAvgCurrent, 4, BigDecimal.ROUND_HALF_UP);
        BigDecimal result = bdArgsA.multiply(bdLoadAvgCurrent);
        result = result.add(bdMax);
        return result.setScale(4, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * @param code
     * @param msg
     */
    private void recordLoggs(String code, String msg) {
        SimpleDateFormat sdfms = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSS");
        this.calLog.append(sdfms.format(Calendar.getInstance().getTime())).append(" -> ").append(msg).append("\n");
        IkgWebUtils.sendMsg(code, msg);
    }
}
